package com.bob.like.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bob.like.constant.BlogConstant;
import com.bob.like.constant.RedisLuaScriptConstant;
import com.bob.like.constant.ThumbConstant;
import com.bob.like.mapper.ThumbMapper;
import com.bob.like.model.dto.DoThumbRequest;
import com.bob.like.model.entity.Blog;
import com.bob.like.model.entity.Thumb;
import com.bob.like.model.entity.User;
import com.bob.like.model.enums.LuaStatusEnum;
import com.bob.like.service.BlogService;
import com.bob.like.service.ThumbService;
import com.bob.like.service.UserService;
import com.bob.like.util.RedisKeyUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

@Service("thumbServiceRedis")
@Slf4j
@RequiredArgsConstructor
public class ThumbServiceRedisImpl extends ServiceImpl<ThumbMapper, Thumb> implements ThumbService {
  
    private final UserService userService;

    private final BlogService blogService;
  
    private final RedisTemplate<String, Object> redisTemplate;
  
    @Override  
    public Boolean doThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {
        if (doThumbRequest == null || doThumbRequest.getBlogId() == null) {  
            throw new RuntimeException("参数错误");  
        }  
        User loginUser = userService.getLoginUser(request);
        Long blogId = doThumbRequest.getBlogId();

        // 先检查是否已点赞
        long currentTimeMillis = System.currentTimeMillis();
        long createTimeMillis = getBlogCreateTime(blogId);
        boolean exists = this.hasThumb(blogId, loginUser.getId());
        if (exists) {
            throw new RuntimeException("用户已点赞");
        }
        if (currentTimeMillis - createTimeMillis > BlogConstant.BLOG_EXPIRE_TIME) {
            Thumb thumb = this.lambdaQuery()
                    .eq(Thumb::getUserId, loginUser.getId())
                    .eq(Thumb::getBlogId, blogId)
                    .one();
            if (thumb != null) {
                throw new RuntimeException("用户已点赞");
            }
        }
        String timeSlice = getTimeSlice();  
        // Redis Key  
        String tempThumbKey = RedisKeyUtil.getTempThumbKey(timeSlice);
        String userThumbKey = RedisKeyUtil.getUserThumbKey(loginUser.getId(),blogId);
  
        // 执行 Lua 脚本  
        long result = redisTemplate.execute(  
                RedisLuaScriptConstant.THUMB_SCRIPT,
                Arrays.asList(tempThumbKey, userThumbKey),
                loginUser.getId(),  
                blogId,
                ThumbConstant.THUMB_EXPIRE_TIME
        );  

  
        // 更新成功才执行  
        return LuaStatusEnum.SUCCESS.getValue() == result;  
    }  
  
    @Override  
    public Boolean undoThumb(DoThumbRequest doThumbRequest, HttpServletRequest request) {  
        if (doThumbRequest == null || doThumbRequest.getBlogId() == null) {  
            throw new RuntimeException("参数错误");  
        }  
        User loginUser = userService.getLoginUser(request);  
  
        Long blogId = doThumbRequest.getBlogId();  
        // 计算时间片  
        String timeSlice = getTimeSlice();  
        // Redis Key  
        String tempThumbKey = RedisKeyUtil.getTempThumbKey(timeSlice);  
        String userThumbKey = RedisKeyUtil.getUserThumbKey(loginUser.getId(),blogId);
  
        // 执行 Lua 脚本  
        long result = redisTemplate.execute(  
                RedisLuaScriptConstant.UNTHUMB_SCRIPT,  
                Arrays.asList(tempThumbKey, userThumbKey),  
                loginUser.getId(),  
                blogId  
        );  
        // 根据返回值处理结果  
        if (result == LuaStatusEnum.FAIL.getValue()) {  
            throw new RuntimeException("用户未点赞");  
        }  
        return LuaStatusEnum.SUCCESS.getValue() == result;  
    }  
  
    private String getTimeSlice() {
        DateTime nowDate = DateUtil.date();
        // 修改当前时间的秒数为 0
        nowDate.setField(java.util.Calendar.SECOND, 0);
        // 修改当前时间的分钟数为最近的整十分钟
        int minute = nowDate.minute();
        nowDate.setField(java.util.Calendar.MINUTE, (minute / 10) * 10);
        return DateUtil.format(nowDate, "HH:mm:ss");
    }

    @Override
    public Boolean hasThumb(Long blogId, Long userId) {
        //return redisTemplate.opsForHash().hasKey(ThumbConstant.USER_THUMB_KEY_PREFIX + userId, blogId.toString());
        return ObjectUtil.isNotNull(redisTemplate.opsForValue().get(RedisKeyUtil.getUserThumbKey(userId,blogId))) ;
    }

    public long getBlogCreateTime(long blogId) {
        Object blogCreateTime = redisTemplate.opsForValue().get(BlogConstant.BLOG_KEY_PREFIX + blogId);
        if(blogCreateTime == null){
            Blog blog = blogService.getById(blogId);
            if(ObjectUtil.isNull(blog)){
                throw new RuntimeException("博客不存在");
            }
            blogCreateTime = blog.getCreateTime().getTime();
            redisTemplate.opsForValue().set(BlogConstant.BLOG_KEY_PREFIX + blogId, blogCreateTime, BlogConstant.BLOG_EXPIRE_TIME, TimeUnit.MILLISECONDS);
        }
        return blogCreateTime instanceof Long ? (Long) blogCreateTime : Long.parseLong(blogCreateTime.toString());
    }
}
